package com.hy.config;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hy.mapper.MedicineBasicInfoMapper;
import com.hy.medicine.MedicineBasicInfo;
import com.hy.medicine.vo.MedicineImportTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;

@Slf4j
public class ImportDataListener implements ReadListener<MedicineImportTemplate> {

    private final MedicineBasicInfoMapper medicineBasicInfoMapper;
    private final ImportResult importResult;
    private final int batchSize;
    private List<MedicineBasicInfo> cachedDataList;
    // 用于存储已经存在的批准文号
    private Set<String> existingApprovalNumbers;
    // 用于存储本次导入的批准文号
    private Set<String> currentImportApprovalNumbers;
    private BiConsumer<MedicineImportTemplate, List<String>> validator;

    // 定义有效的通用分类ID列表
    private static final List<String> VALID_COMMON_CATEGORIES = Arrays.asList(
        "andrology", "cold", "dermatology", "digestive", "ent",
        "gynecology", "neurology", "nutrition", "pediatric",
        "respiratory", "rheumatism", "rx"
    );

    // 定义有效的处方分类ID列表
    private static final List<String> VALID_PRESCRIPTION_CATEGORIES = Arrays.asList(
        "otc", "rx"
    );

    public ImportDataListener(MedicineBasicInfoMapper mapper, ImportResult result, int batchSize, BiConsumer<MedicineImportTemplate, List<String>> validator) {
        this.medicineBasicInfoMapper = mapper;
        this.importResult = result;
        this.batchSize = batchSize;
        this.cachedDataList = new ArrayList<>(batchSize);
        this.existingApprovalNumbers = new HashSet<>();
        this.currentImportApprovalNumbers = new HashSet<>();
        this.validator = validator;

        // 初始化时加载所有已存在的批准文号
        List<String> existingNumbers = medicineBasicInfoMapper.selectAllApprovalNumbers();
        if (existingNumbers != null) {
            this.existingApprovalNumbers.addAll(existingNumbers);
        }
    }

    @Override
    public void invoke(MedicineImportTemplate data, AnalysisContext context) {
        int rowIndex = context.readRowHolder().getRowIndex() + 1;
        try {
            log.info("正在处理第{}行数据: {}", rowIndex, data);

            // 检查价格字段
            if (data.getPrice() != null) {
                log.info("第{}行价格数据: {}", rowIndex, data.getPrice());
            } else {
                log.warn("第{}行价格为空", rowIndex);
            }

            // 检查批准文号是否重复
            if (existingApprovalNumbers.contains(data.getApprovalNumber())) {
                handleError(context, "批准文号已存在: " + data.getApprovalNumber());
                return;
            }

            // 检查本次导入是否有重复的批准文号
            if (currentImportApprovalNumbers.contains(data.getApprovalNumber())) {
                handleError(context, "Excel中存在重复的批准文号: " + data.getApprovalNumber());
                return;
            }

            // 记录本次导入的批准文号
            currentImportApprovalNumbers.add(data.getApprovalNumber());

            // 1. 先检查价格字段
            if (data.getPrice() == null) {
                handleError(context, "单价不能为空");
                return;
            }

            // 2. 数据预处理
            try {
                preProcess(data);
            } catch (Exception e) {
                handleError(context, "第" + rowIndex + "行: " + e.getMessage());
                return;
            }

            // 3. 数据校验
            try {
                validateData(data, context);
            } catch (Exception e) {
                handleError(context, "第" + rowIndex + "行: " + e.getMessage());
                return;
            }

            // 4. 转换为实体对象
            try {
                MedicineBasicInfo medicineInfo = convertToEntity(data);
                cachedDataList.add(medicineInfo);
                importResult.addSuccessCount(1);

                // 达到批量处理数量时保存
                if (cachedDataList.size() >= batchSize) {
                    saveData();
                    cachedDataList = new ArrayList<>(batchSize);
                }
            } catch (Exception e) {
                handleError(context, "第" + rowIndex + "行: 数据转换失败 - " + e.getMessage());
            }
        } catch (Exception e) {
            log.error("处理第{}行数据时发生错误: {}", rowIndex, e.getMessage());
            handleError(context, e.getMessage());
        }
    }

    private void preProcess(MedicineImportTemplate data) {
        log.info("正在处理数据: {}", data);

        // 处理价格
        if (data.getPrice() != null) {
            log.info("处理价格字段: {}", data.getPrice());
            if (data.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
                throw new RuntimeException("单价必须大于0");
            }
            data.setPrice(data.getPrice().setScale(2, RoundingMode.HALF_UP));
        }

        // 处理字符串字段，去除前后空格
        if (data.getMedicineName() != null) {
            data.setMedicineName(data.getMedicineName().trim());
        }
        if (data.getManufacturer() != null) {
            data.setManufacturer(data.getManufacturer().trim());
        }
        if (data.getStorageCondition() != null) {
            data.setStorageCondition(data.getStorageCondition().trim());
        }
    }

    private void validateData(MedicineImportTemplate data, AnalysisContext context) {
        StringBuilder errors = new StringBuilder();

        // 必填字段验证
        if (StringUtils.isBlank(data.getMedicineName())) {
            errors.append("药品名称不能为空; ");
        }
        if (StringUtils.isBlank(data.getApprovalNumber())) {
            errors.append("批准文号不能为空; ");
        }
        if (StringUtils.isBlank(data.getSpecification())) {
            errors.append("规格不能为空; ");
        }
        if (StringUtils.isBlank(data.getDosageForm())) {
            errors.append("剂型不能为空; ");
        }
        if (StringUtils.isBlank(data.getManufacturer())) {
            errors.append("生产厂家不能为空; ");
        }
        if (data.getShelfLife() == null) {
            errors.append("保质期不能为空; ");
        } else if (data.getShelfLife() <= 0) {
            errors.append("保质期必须大于0个月; ");
        }
        if (StringUtils.isBlank(data.getStorageCondition())) {
            errors.append("储存条件不能为空; ");
        }
        if (data.getPrice() == null) {
            errors.append("单价不能为空; ");
        }

        // 验证分类ID
        List<String> validationErrors = new ArrayList<>();
        validator.accept(data, validationErrors);
        if (!validationErrors.isEmpty()) {
            errors.append(String.join("; ", validationErrors));
        }

        // 如果有错误，抛出异常
        if (errors.length() > 0) {
            throw new RuntimeException(errors.toString());
        }
    }

    private void handleError(AnalysisContext context, String message) {
        int rowIndex = context.readRowHolder().getRowIndex() + 1;
        importResult.addFailCount(1);
        importResult.addErrorMessage(String.format("第%d行: %s", rowIndex, message));
        log.error("导入错误 - {}", message);
    }

    private void saveData() {
        if (!cachedDataList.isEmpty()) {
            try {
                medicineBasicInfoMapper.batchInsert(cachedDataList);
                // 保存成功后，将批准文号添加到已存在集合中
                for (MedicineBasicInfo medicine : cachedDataList) {
                    existingApprovalNumbers.add(medicine.getApprovalNumber());
                }
            } catch (Exception e) {
                log.error("批量保存数据失败", e);
                importResult.addFailCount(cachedDataList.size());
                String errorMsg = e.getMessage();
                if (errorMsg.contains("Duplicate entry")) {
                    errorMsg = "存在重复的批准文号，请检查数据";
                }
                importResult.addErrorMessage("批量保存失败: " + errorMsg);
                // 重置成功计数
                importResult.setSuccessCount(importResult.getSuccessCount() - cachedDataList.size());
            }
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
        log.info("导入完成 - 成功: {}, 失败: {}",
                importResult.getSuccessCount(),
                importResult.getFailCount());
    }

    /**
     * 将导入模板数据转换为实体对象
     *
     * @param data 医药导入模板对象
     * @return 返回转换后的医药基本信息实体对象
     */
    private MedicineBasicInfo convertToEntity(MedicineImportTemplate data) {
        // 创建一个新的医药基本信息实体对象
        MedicineBasicInfo entity = new MedicineBasicInfo();
        // 将导入模板对象的属性复制到实体对象中
        BeanUtils.copyProperties(data, entity);
        // 设置库存量，如果导入模板中的库存为null，则设置为0
        entity.setSalesVolume(data.getMinStock() != null ? data.getMinStock() : 0);
        // 返回转换后的实体对象
        return entity;
    }
}
